/**************************************************************************
*   Copyleft 2009 by        											  *
*	Iwanicki Krzysztof													  *
*   <www.gamma.mini.pw.edu.pl/~iwanickik>		                          *
*                                                                         *
*   This program is free software; you can redistribute it and/or modify  *
*   it under the terms of the GNU General Public License as published by  *
*   the Free Software Foundation; either version 2 of the License, or     *
*   (at your option) any later version.                                   *
*                                                                         *
*   This program is distributed in the hope that it will be useful,       *
*   but WITHOUT ANY WARRANTY; without even the implied warranty of        *
*   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the         *
*   GNU General Public License for more details.                          *
***************************************************************************/
#include "./vSceneManager.h"
#include "../Viewport/vFreeLookCamera.h"


namespace Vendetta {
	vSceneManager::vSceneManager() {
		mpActiveCamera = vNull;
	}
	
	vSceneManager::~vSceneManager() {
		for (vUInt uiInd = 0; uiInd < mCameras.Size(); uiInd++) {
			vDelete(mCameras[uiInd]);
		}
		// TODO: add light class later.
		//for (vUInt uiInd = 0; uiInd < mLights.Size(); uiInd++) {
		//	vDelete(mLights[uiInd]);
		//}
		mCameras.Clear();
		mLights.Clear();
	}

	vCamera* vSceneManager::CreateCamera(const vString& name) {
		vBool bIsIn = false;

		vString camName;
		for (vUInt uiInd = 0; uiInd < mCameras.Size(); uiInd++) {
			camName = mCameras[uiInd]->Name();
			if (camName.IsEqual(name)) {
				bIsIn = true;
				break;
			}
		}

		if (bIsIn || name.IsEmpty()) {
			throw vFatalException("Camera with name \"%s\" already exists or name should not be empty. In vSceneManager::CreateCamera.", 
				name.ToConstCharPtr());
		} else {
			// TODO: add camera creation.
			mpActiveCamera = new vFreeLookCamera(name);
			mCameras.AddAsLast(mpActiveCamera);

			return mpActiveCamera;
		}

		return vNull;
	}

	vBool vSceneManager::RemoveCamera(vCamera* pCamera) {
		if (mCameras.Contains(pCamera)) {
			vUInt uiInd = mCameras.Find(pCamera);
			vDelete(mCameras[uiInd]);
			mCameras.Remove(uiInd);
			if (mpActiveCamera == mCameras[uiInd]) {
				mpActiveCamera = vNull;
			}

			return true;
		}

		return false;
	}

	vBool vSceneManager::RemoveCamera(const vString& name) {
		if (name.IsEmpty()) {
			return false;
		}

		vString camName;
		for (vUInt uiInd = 0; uiInd < mCameras.Size(); uiInd++) {
			camName = mCameras[uiInd]->Name();
			if (camName.IsEqual(name)) {
				vDelete(mCameras[uiInd]);
				mCameras.Remove(uiInd);
				if (mpActiveCamera == mCameras[uiInd]) {
					mpActiveCamera = vNull;
				}
				
				return true;
			}
		}

		return false;
	}

	vVoid vSceneManager::UseCamera(vCamera* pCamera) {
		if (!pCamera || !mCameras.Contains(pCamera)) {
			throw vFatalException("You try to use not existing camera. In vSceneManager::UseCamera.");
		}
		mpActiveCamera = pCamera;
	}

	vVoid vSceneManager::UseCamera(const vString& name) {
		if (!name.IsEmpty()) {
			vString camName;
			for (vUInt uiInd = 0; uiInd < mCameras.Size(); uiInd++) {
				camName = mCameras[uiInd]->Name();
				if (camName.IsEqual(name)) {
					mpActiveCamera = mCameras[uiInd];

					return;
				}
			}
		}
		throw vFatalException("You try to use not existing camera. In vSceneManager::UseCamera."); 
	}

	vVoid vSceneManager::Update(const vFrameListener::vFrameEvent& event) {
		if (mpActiveCamera) {
			mpActiveCamera->Update(event);
		}
	}

	vVoid vSceneManager::SetupCamera() {
		if (mpActiveCamera) {
			mpActiveCamera->Use();
		}
	}

	/************************************************************************/
	/* Disabled                                                             */
	/************************************************************************/
	vSceneManager::vSceneManager(const vSceneManager& sceneManager) { 
		V_CHECK_MSG(0, "Some tries to call vSceneManager copy ctor.") ;
	}

	vSceneManager& vSceneManager::operator=(const vSceneManager& sceneManager) { 
		V_CHECK_MSG(0, "Some tries to call vSceneManager operator=."); 
		return * this; 
	}
	/************************************************************************/
}